﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.GraphicsBuffer
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Bindings;
using UnityEngine.Scripting;

#nullable disable
namespace UnityEngine
{
  /// <summary>
  ///   <para>GPU graphics data buffer, for working with geometry or compute shader data.</para>
  /// </summary>
  [NativeHeader("Runtime/Export/Graphics/GraphicsBuffer.bindings.h")]
  [UsedByNativeCode]
  [NativeHeader("Runtime/Shaders/GraphicsBuffer.h")]
  public sealed class GraphicsBuffer : IDisposable
  {
    internal IntPtr m_Ptr;

    ~GraphicsBuffer() => this.Dispose(false);

    public void Dispose()
    {
      this.Dispose(true);
      GC.SuppressFinalize((object) this);
    }

    private void Dispose(bool disposing)
    {
      if (disposing)
      {
        GraphicsBuffer.DestroyBuffer(this);
        this.RemoveBufferFromLeakDetector();
      }
      else if (this.m_Ptr != IntPtr.Zero && UnsafeUtility.GetLeakDetectionMode() == NativeLeakDetectionMode.Disabled)
        Debug.LogWarning((object) "GarbageCollector disposing of GraphicsBuffer. Please use GraphicsBuffer.Release() or .Dispose() to manually release the buffer. To see the stack trace where the leaked resource was allocated, set the UnsafeUtility LeakDetectionMode to EnabledWithStackTrace.");
      this.m_Ptr = IntPtr.Zero;
    }

    private static bool RequiresCompute(GraphicsBuffer.Target target)
    {
      GraphicsBuffer.Target target1 = GraphicsBuffer.Target.Structured | GraphicsBuffer.Target.Raw | GraphicsBuffer.Target.Append | GraphicsBuffer.Target.Counter | GraphicsBuffer.Target.IndirectArguments;
      return (target & target1) != 0;
    }

    private static bool IsVertexIndexOrCopyOnly(GraphicsBuffer.Target target)
    {
      GraphicsBuffer.Target target1 = GraphicsBuffer.Target.Vertex | GraphicsBuffer.Target.Index | GraphicsBuffer.Target.CopySource | GraphicsBuffer.Target.CopyDestination;
      return (target & target1) == target;
    }

    [FreeFunction("GraphicsBuffer_Bindings::InitBuffer")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern IntPtr InitBuffer(GraphicsBuffer.Target target, int count, int stride);

    [FreeFunction("GraphicsBuffer_Bindings::DestroyBuffer")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void DestroyBuffer(GraphicsBuffer buf);

    public GraphicsBuffer(GraphicsBuffer.Target target, int count, int stride)
    {
      if (GraphicsBuffer.RequiresCompute(target) && !SystemInfo.supportsComputeShaders)
        throw new ArgumentException("Attempting to create a graphics buffer that requires compute shader support, but compute shaders are not supported on this platform. Target: " + target.ToString());
      if (count <= 0)
        throw new ArgumentException("Attempting to create a zero length graphics buffer", nameof (count));
      if (stride <= 0)
        throw new ArgumentException("Attempting to create a graphics buffer with a negative or null stride", nameof (stride));
      if ((target & GraphicsBuffer.Target.Index) != (GraphicsBuffer.Target) 0 && stride != 2 && stride != 4)
        throw new ArgumentException("Attempting to create an index buffer with an invalid stride: " + stride.ToString(), nameof (stride));
      if (!GraphicsBuffer.IsVertexIndexOrCopyOnly(target) && stride % 4 != 0)
        throw new ArgumentException("Stride must be a multiple of 4 unless the buffer is only used as a vertex buffer and/or index buffer ", nameof (stride));
      long num = (long) count * (long) stride;
      long graphicsBufferSize = SystemInfo.maxGraphicsBufferSize;
      if (num > graphicsBufferSize)
        throw new ArgumentException(string.Format("The total size of the graphics buffer ({0} bytes) exceeds the maximum buffer size. Maximum supported buffer size: {1} bytes.", (object) num, (object) graphicsBufferSize));
      this.m_Ptr = GraphicsBuffer.InitBuffer(target, count, stride);
      this.AddBufferToLeakDetector();
    }

    /// <summary>
    ///   <para>Release a Graphics Buffer.</para>
    /// </summary>
    public void Release() => this.Dispose();

    [FreeFunction("GraphicsBuffer_Bindings::IsValidBuffer")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern bool IsValidBuffer(GraphicsBuffer buf);

    /// <summary>
    ///   <para>Returns true if this graphics buffer is valid, or false otherwise.</para>
    /// </summary>
    public bool IsValid() => this.m_Ptr != IntPtr.Zero && GraphicsBuffer.IsValidBuffer(this);

    /// <summary>
    ///   <para>Number of elements in the buffer (Read Only).</para>
    /// </summary>
    public extern int count { [MethodImpl(MethodImplOptions.InternalCall)] get; }

    /// <summary>
    ///   <para>Size of one element in the buffer. For index buffers, this must be either 2 or 4 bytes (Read Only).</para>
    /// </summary>
    public extern int stride { [MethodImpl(MethodImplOptions.InternalCall)] get; }

    /// <summary>
    ///   <para>Usage target, which specifies the intended usage of this GraphicsBuffer (Read Only).</para>
    /// </summary>
    public extern GraphicsBuffer.Target target { [MethodImpl(MethodImplOptions.InternalCall)] get; }

    /// <summary>
    ///   <para>Set the buffer with values from an array.</para>
    /// </summary>
    /// <param name="data">Array of values to fill the buffer.</param>
    [SecuritySafeCritical]
    public void SetData(Array data)
    {
      if (data == null)
        throw new ArgumentNullException(nameof (data));
      if (!UnsafeUtility.IsArrayBlittable(data))
        throw new ArgumentException(string.Format("Array passed to GraphicsBuffer.SetData(array) must be blittable.\n{0}", (object) UnsafeUtility.GetReasonForArrayNonBlittable(data)));
      this.InternalSetData(data, 0, 0, data.Length, UnsafeUtility.SizeOf(data.GetType().GetElementType()));
    }

    [SecuritySafeCritical]
    public void SetData<T>(List<T> data) where T : struct
    {
      if (data == null)
        throw new ArgumentNullException(nameof (data));
      if (!UnsafeUtility.IsGenericListBlittable<T>())
        throw new ArgumentException(string.Format("List<{0}> passed to GraphicsBuffer.SetData(List<>) must be blittable.\n{1}", (object) typeof (T), (object) UnsafeUtility.GetReasonForGenericListNonBlittable<T>()));
      this.InternalSetData(NoAllocHelpers.ExtractArrayFromList((object) data), 0, 0, NoAllocHelpers.SafeLength<T>(data), Marshal.SizeOf(typeof (T)));
    }

    [SecuritySafeCritical]
    public unsafe void SetData<T>(NativeArray<T> data) where T : struct
    {
      this.InternalSetNativeData((IntPtr) data.GetUnsafeReadOnlyPtr<T>(), 0, 0, data.Length, UnsafeUtility.SizeOf<T>());
    }

    /// <summary>
    ///   <para>Partial copy of data values from an array into the buffer.</para>
    /// </summary>
    /// <param name="data">Array of values to fill the buffer.</param>
    /// <param name="managedBufferStartIndex">The first element index in data to copy to the graphics buffer.</param>
    /// <param name="count">The number of elements to copy.</param>
    /// <param name="graphicsBufferStartIndex">The first element index in the graphics buffer to receive the data.</param>
    /// <param name="nativeBufferStartIndex"></param>
    [SecuritySafeCritical]
    public void SetData(
      Array data,
      int managedBufferStartIndex,
      int graphicsBufferStartIndex,
      int count)
    {
      if (data == null)
        throw new ArgumentNullException(nameof (data));
      if (!UnsafeUtility.IsArrayBlittable(data))
        throw new ArgumentException(string.Format("Array passed to GraphicsBuffer.SetData(array) must be blittable.\n{0}", (object) UnsafeUtility.GetReasonForArrayNonBlittable(data)));
      if (managedBufferStartIndex < 0 || graphicsBufferStartIndex < 0 || count < 0 || managedBufferStartIndex + count > data.Length)
        throw new ArgumentOutOfRangeException(string.Format("Bad indices/count arguments (managedBufferStartIndex:{0} graphicsBufferStartIndex:{1} count:{2})", (object) managedBufferStartIndex, (object) graphicsBufferStartIndex, (object) count));
      this.InternalSetData(data, managedBufferStartIndex, graphicsBufferStartIndex, count, Marshal.SizeOf(data.GetType().GetElementType()));
    }

    [SecuritySafeCritical]
    public void SetData<T>(
      List<T> data,
      int managedBufferStartIndex,
      int graphicsBufferStartIndex,
      int count)
      where T : struct
    {
      if (data == null)
        throw new ArgumentNullException(nameof (data));
      if (!UnsafeUtility.IsGenericListBlittable<T>())
        throw new ArgumentException(string.Format("List<{0}> passed to GraphicsBuffer.SetData(List<>) must be blittable.\n{1}", (object) typeof (T), (object) UnsafeUtility.GetReasonForGenericListNonBlittable<T>()));
      if (managedBufferStartIndex < 0 || graphicsBufferStartIndex < 0 || count < 0 || managedBufferStartIndex + count > data.Count)
        throw new ArgumentOutOfRangeException(string.Format("Bad indices/count arguments (managedBufferStartIndex:{0} graphicsBufferStartIndex:{1} count:{2})", (object) managedBufferStartIndex, (object) graphicsBufferStartIndex, (object) count));
      this.InternalSetData(NoAllocHelpers.ExtractArrayFromList((object) data), managedBufferStartIndex, graphicsBufferStartIndex, count, Marshal.SizeOf(typeof (T)));
    }

    [SecuritySafeCritical]
    public unsafe void SetData<T>(
      NativeArray<T> data,
      int nativeBufferStartIndex,
      int graphicsBufferStartIndex,
      int count)
      where T : struct
    {
      if (nativeBufferStartIndex < 0 || graphicsBufferStartIndex < 0 || count < 0 || nativeBufferStartIndex + count > data.Length)
        throw new ArgumentOutOfRangeException(string.Format("Bad indices/count arguments (nativeBufferStartIndex:{0} graphicsBufferStartIndex:{1} count:{2})", (object) nativeBufferStartIndex, (object) graphicsBufferStartIndex, (object) count));
      this.InternalSetNativeData((IntPtr) data.GetUnsafeReadOnlyPtr<T>(), nativeBufferStartIndex, graphicsBufferStartIndex, count, UnsafeUtility.SizeOf<T>());
    }

    [SecurityCritical]
    [FreeFunction(Name = "GraphicsBuffer_Bindings::InternalSetNativeData", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void InternalSetNativeData(
      IntPtr data,
      int nativeBufferStartIndex,
      int graphicsBufferStartIndex,
      int count,
      int elemSize);

    [SecurityCritical]
    [FreeFunction(Name = "GraphicsBuffer_Bindings::InternalSetData", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void InternalSetData(
      Array data,
      int managedBufferStartIndex,
      int graphicsBufferStartIndex,
      int count,
      int elemSize);

    /// <summary>
    ///   <para>Read data values from the buffer into an array. The array can only use &lt;a href="https:docs.microsoft.comen-usdotnetframeworkinteropblittable-and-non-blittable-types"&gt;blittable&lt;a&gt; types.</para>
    /// </summary>
    /// <param name="data">An array to receive the data.</param>
    /// <param name="managedBufferStartIndex">The first element index in data where retrieved elements are copied.</param>
    /// <param name="computeBufferStartIndex">The first element index of the buffer from which elements are read.</param>
    /// <param name="count">The number of elements to retrieve.</param>
    [SecurityCritical]
    public void GetData(Array data)
    {
      if (data == null)
        throw new ArgumentNullException(nameof (data));
      if (!UnsafeUtility.IsArrayBlittable(data))
        throw new ArgumentException(string.Format("Array passed to GraphicsBuffer.GetData(array) must be blittable.\n{0}", (object) UnsafeUtility.GetReasonForArrayNonBlittable(data)));
      this.InternalGetData(data, 0, 0, data.Length, Marshal.SizeOf(data.GetType().GetElementType()));
    }

    /// <summary>
    ///   <para>Read data values from the buffer into an array. The array can only use &lt;a href="https:docs.microsoft.comen-usdotnetframeworkinteropblittable-and-non-blittable-types"&gt;blittable&lt;a&gt; types.</para>
    /// </summary>
    /// <param name="data">An array to receive the data.</param>
    /// <param name="managedBufferStartIndex">The first element index in data where retrieved elements are copied.</param>
    /// <param name="computeBufferStartIndex">The first element index of the buffer from which elements are read.</param>
    /// <param name="count">The number of elements to retrieve.</param>
    [SecurityCritical]
    public void GetData(
      Array data,
      int managedBufferStartIndex,
      int computeBufferStartIndex,
      int count)
    {
      if (data == null)
        throw new ArgumentNullException(nameof (data));
      if (!UnsafeUtility.IsArrayBlittable(data))
        throw new ArgumentException(string.Format("Array passed to GraphicsBuffer.GetData(array) must be blittable.\n{0}", (object) UnsafeUtility.GetReasonForArrayNonBlittable(data)));
      if (managedBufferStartIndex < 0 || computeBufferStartIndex < 0 || count < 0 || managedBufferStartIndex + count > data.Length)
        throw new ArgumentOutOfRangeException(string.Format("Bad indices/count argument (managedBufferStartIndex:{0} computeBufferStartIndex:{1} count:{2})", (object) managedBufferStartIndex, (object) computeBufferStartIndex, (object) count));
      this.InternalGetData(data, managedBufferStartIndex, computeBufferStartIndex, count, Marshal.SizeOf(data.GetType().GetElementType()));
    }

    [SecurityCritical]
    [FreeFunction(Name = "GraphicsBuffer_Bindings::InternalGetData", HasExplicitThis = true, ThrowsException = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void InternalGetData(
      Array data,
      int managedBufferStartIndex,
      int computeBufferStartIndex,
      int count,
      int elemSize);

    /// <summary>
    ///   <para>Retrieve a native (underlying graphics API) pointer to the buffer.</para>
    /// </summary>
    /// <returns>
    ///   <para>Pointer to the underlying graphics API buffer.</para>
    /// </returns>
    [FreeFunction(Name = "GraphicsBuffer_Bindings::InternalGetNativeBufferPtr", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern IntPtr GetNativeBufferPtr();

    /// <summary>
    ///   <para>The debug label for the graphics buffer (setter only).</para>
    /// </summary>
    public string name
    {
      set => this.SetName(value);
    }

    [FreeFunction(Name = "GraphicsBuffer_Bindings::SetName", HasExplicitThis = true)]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private extern void SetName(string name);

    /// <summary>
    ///   <para>Sets counter value of append/consume buffer.</para>
    /// </summary>
    /// <param name="counterValue">Value of the append/consume counter.</param>
    [MethodImpl(MethodImplOptions.InternalCall)]
    public extern void SetCounterValue(uint counterValue);

    [FreeFunction(Name = "GraphicsBuffer_Bindings::CopyCount")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void CopyCountCC(
      ComputeBuffer src,
      ComputeBuffer dst,
      int dstOffsetBytes);

    [FreeFunction(Name = "GraphicsBuffer_Bindings::CopyCount")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void CopyCountGC(
      GraphicsBuffer src,
      ComputeBuffer dst,
      int dstOffsetBytes);

    [FreeFunction(Name = "GraphicsBuffer_Bindings::CopyCount")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void CopyCountCG(
      ComputeBuffer src,
      GraphicsBuffer dst,
      int dstOffsetBytes);

    [FreeFunction(Name = "GraphicsBuffer_Bindings::CopyCount")]
    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void CopyCountGG(
      GraphicsBuffer src,
      GraphicsBuffer dst,
      int dstOffsetBytes);

    /// <summary>
    ///   <para>Copy the counter value of a GraphicsBuffer into another buffer.</para>
    /// </summary>
    /// <param name="src">The source GraphicsBuffer.</param>
    /// <param name="dst">The destination GraphicsBuffer.</param>
    /// <param name="dstOffsetBytes">The destination buffer offset in bytes.</param>
    public static void CopyCount(ComputeBuffer src, ComputeBuffer dst, int dstOffsetBytes)
    {
      GraphicsBuffer.CopyCountCC(src, dst, dstOffsetBytes);
    }

    /// <summary>
    ///   <para>Copy the counter value of a GraphicsBuffer into another buffer.</para>
    /// </summary>
    /// <param name="src">The source GraphicsBuffer.</param>
    /// <param name="dst">The destination GraphicsBuffer.</param>
    /// <param name="dstOffsetBytes">The destination buffer offset in bytes.</param>
    public static void CopyCount(GraphicsBuffer src, ComputeBuffer dst, int dstOffsetBytes)
    {
      GraphicsBuffer.CopyCountGC(src, dst, dstOffsetBytes);
    }

    /// <summary>
    ///   <para>Copy the counter value of a GraphicsBuffer into another buffer.</para>
    /// </summary>
    /// <param name="src">The source GraphicsBuffer.</param>
    /// <param name="dst">The destination GraphicsBuffer.</param>
    /// <param name="dstOffsetBytes">The destination buffer offset in bytes.</param>
    public static void CopyCount(ComputeBuffer src, GraphicsBuffer dst, int dstOffsetBytes)
    {
      GraphicsBuffer.CopyCountCG(src, dst, dstOffsetBytes);
    }

    /// <summary>
    ///   <para>Copy the counter value of a GraphicsBuffer into another buffer.</para>
    /// </summary>
    /// <param name="src">The source GraphicsBuffer.</param>
    /// <param name="dst">The destination GraphicsBuffer.</param>
    /// <param name="dstOffsetBytes">The destination buffer offset in bytes.</param>
    public static void CopyCount(GraphicsBuffer src, GraphicsBuffer dst, int dstOffsetBytes)
    {
      GraphicsBuffer.CopyCountGG(src, dst, dstOffsetBytes);
    }

    internal void AddBufferToLeakDetector()
    {
      IntPtr ptr = this.m_Ptr;
      if (false)
        return;
      UnsafeUtility.LeakRecord(this.m_Ptr, LeakCategory.Persistent, 2);
    }

    internal void RemoveBufferFromLeakDetector()
    {
      IntPtr ptr = this.m_Ptr;
      if (false)
        return;
      UnsafeUtility.LeakErase(this.m_Ptr, LeakCategory.Persistent);
    }

    /// <summary>
    ///   <para>The intended usage of a GraphicsBuffer.</para>
    /// </summary>
    [Flags]
    public enum Target
    {
      /// <summary>
      ///   <para>GraphicsBuffer can be used as a vertex buffer.</para>
      /// </summary>
      Vertex = 1,
      /// <summary>
      ///   <para>GraphicsBuffer can be used as an index buffer.</para>
      /// </summary>
      Index = 2,
      /// <summary>
      ///   <para>GraphicsBuffer can be used as a source for CopyBuffer.</para>
      /// </summary>
      CopySource = 4,
      /// <summary>
      ///   <para>GraphicsBuffer can be used as a destination for CopyBuffer.</para>
      /// </summary>
      CopyDestination = 8,
      /// <summary>
      ///   <para>GraphicsBuffer can be used as a structured buffer.</para>
      /// </summary>
      Structured = 16, // 0x00000010
      /// <summary>
      ///   <para>GraphicsBuffer can be used as a raw byte-address buffer.</para>
      /// </summary>
      Raw = 32, // 0x00000020
      /// <summary>
      ///   <para>GraphicsBuffer can be used as an append-consume buffer.</para>
      /// </summary>
      Append = 64, // 0x00000040
      /// <summary>
      ///   <para>GraphicsBuffer with an internal counter.</para>
      /// </summary>
      Counter = 128, // 0x00000080
      /// <summary>
      ///   <para>GraphicsBuffer can be used as an indirect argument buffer for indirect draws and dispatches.</para>
      /// </summary>
      IndirectArguments = 256, // 0x00000100
      /// <summary>
      ///   <para>GraphicsBuffer can be used as a constant buffer (uniform buffer).</para>
      /// </summary>
      Constant = 512, // 0x00000200
    }

    /// <summary>
    ///   <para>Defines the data layout for non-indexed indirect render calls.</para>
    /// </summary>
    public struct IndirectDrawArgs
    {
      /// <summary>
      ///   <para>The size of the struct in bytes.</para>
      /// </summary>
      public const int size = 16;

      /// <summary>
      ///   <para>The number of vertices per instance.</para>
      /// </summary>
      public uint vertexCountPerInstance { get; set; }

      /// <summary>
      ///   <para>The number of instances to render.</para>
      /// </summary>
      public uint instanceCount { get; set; }

      /// <summary>
      ///   <para>The first vertex to render.</para>
      /// </summary>
      public uint startVertex { get; set; }

      /// <summary>
      ///   <para>The first instance to render.</para>
      /// </summary>
      public uint startInstance { get; set; }
    }

    /// <summary>
    ///   <para>Defines the data layout for indexed indirect render calls.</para>
    /// </summary>
    public struct IndirectDrawIndexedArgs
    {
      /// <summary>
      ///   <para>The size of the struct in bytes.</para>
      /// </summary>
      public const int size = 20;

      /// <summary>
      ///   <para>The number of vertex indices per instance.</para>
      /// </summary>
      public uint indexCountPerInstance { get; set; }

      /// <summary>
      ///   <para>The number of instances to render.</para>
      /// </summary>
      public uint instanceCount { get; set; }

      /// <summary>
      ///   <para>The first index to use in the index buffer of the rendering call.</para>
      /// </summary>
      public uint startIndex { get; set; }

      /// <summary>
      ///   <para>The index to add to values fetched from the index buffer.</para>
      /// </summary>
      public uint baseVertexIndex { get; set; }

      /// <summary>
      ///   <para>The first instance to render.</para>
      /// </summary>
      public uint startInstance { get; set; }
    }
  }
}
